import java.util.*;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;

public class State{
	public static int board_dimension = 5;
	public static char cNull = '\u0000';
	private char turn; // W or B
	private boolean whiteQueenSideCastleAvailable = false;
	private boolean blackQueenSideCastleAvailable = false;
	private boolean whiteKingSideCastleAvailable = false;
	private boolean blackKingSideCastleAvailable = false;
	
	private int empazantablePawnColumn=-1;
	private int empazantablePawnRow=-1;
	
	private Board board;
	
	public State() {
		this.board = new Board(board_dimension);
	}
	
	public State(byte[] bytes){
		BitSet state = toBitSet(bytes);
		int i,j;
		boolean hasPiece[][] = new boolean[board_dimension][board_dimension];
		int cursor = 0;
		
		this.board = new Board(board_dimension);
		
		if (state.get(cursor)){
			setTurn('B');
		}
		else{
			setTurn('W');
		}
		cursor++;
		if (state.get(cursor)){
			whiteQueenSideCastleAvailable=true;
		}
		cursor++;
		if (state.get(cursor)){
			whiteKingSideCastleAvailable=true;
		}
		cursor++;
		if (state.get(cursor)){
			blackQueenSideCastleAvailable=true;
		}
		cursor++;
		if (state.get(cursor)){
			blackKingSideCastleAvailable=true;
		}
		cursor++;
		for (i=0;i<board_dimension;i++){
			for(j=0;j<board_dimension;j++){
				if (state.get(cursor)){
					hasPiece[i][j] = true;
				}
				cursor++;
			}
		}
		char color, piece=cNull;
		for (i=0;i<board_dimension;i++){
			for(j=0;j<board_dimension;j++){
				if (hasPiece[i][j]){
					if (state.get(cursor)){
						color = 'B';
					}
					else{
						color = 'W';
					}
					cursor++;
					if (!state.get(cursor)&&!state.get(cursor+1)&&state.get(cursor+2)){ //001
						piece = 'K';
					}
					else if (!state.get(cursor)&&state.get(cursor+1)&&!state.get(cursor+2)){ //010
						piece = 'Q';
					}
					else if (!state.get(cursor)&&state.get(cursor+1) && state.get(cursor+2)){ //011
						piece = 'R';
					}
					else if (state.get(cursor)&&!state.get(cursor+1)&&!state.get(cursor+2)){ //100
						piece = 'N';
					}
					else if (state.get(cursor)&&!state.get(cursor+1)&&state.get(cursor+2)){ //101
						piece = 'B';
					}
					else if (state.get(cursor)&&state.get(cursor+1)&&!state.get(cursor+2)){ //110
						piece = 'P';
						this.empazantablePawnColumn = j;
						this.empazantablePawnRow = i;
					}
					else if (state.get(cursor) && state.get(cursor+1) && state.get(cursor+2)){ //111
						piece = 'P';
					}
					this.board.setPiece(i,j, new Piece(color, piece));
					cursor+=3;
					
				}
			}
		}
		
	}
	
	public State(char turn, boolean whiteQueenSideCastleAvailable, boolean blackQueenSideCastleAvailable, boolean whiteKingSideCastleAvailable, boolean blackKingSideCastleAvailable, Board boardSetup) {
		this.turn = turn;
		this.whiteQueenSideCastleAvailable = whiteQueenSideCastleAvailable;
		this.blackQueenSideCastleAvailable = blackQueenSideCastleAvailable;
		this.whiteKingSideCastleAvailable = whiteKingSideCastleAvailable;
		this.blackKingSideCastleAvailable = blackKingSideCastleAvailable;
		this.board = boardSetup.clone();
	}
	
	public void setTurn(char color){
		if (color=='W'){
			turn = 'W';
		}
		else{
			turn = 'B';
		}
	}
	
	public char getTurn(){
		return turn;
	}
	/*
	 * color: W or B
	 * side: K or Q
	 */
	public void setCastleAvailability(char color, char side){
		if (color=='W' && side=='K')
			whiteKingSideCastleAvailable = true;
		else if (color=='B' && side=='K')
			blackKingSideCastleAvailable = true;
		else if (color=='W' && side=='Q')
			whiteQueenSideCastleAvailable = true;
		else if (color=='B' && side=='Q')
			blackQueenSideCastleAvailable = true;
	}
	
	public void unsetCastleAvailability(char color, char side){
		if (color=='W' && side=='K')
			whiteKingSideCastleAvailable = false;
		else if (color=='B' && side=='K')
			blackKingSideCastleAvailable = false;
		else if (color=='W' && side=='Q')
			whiteQueenSideCastleAvailable = false;
		else if (color=='B' && side=='Q')
			blackQueenSideCastleAvailable = false;
	}
	
	private int getColumnNumber(char column){
		return (int) column - 97; // get the ascii equivalent and subtract 97 for a
	}
	
	/* Pass the square the pawn is on such as e4 or g5 */
	public void setEmpazantablePawn(int column, int row){
		empazantablePawnColumn = column;
		empazantablePawnRow = row;
	}
	
	/* 
	 * color = W or B
	 * piece = P, R, N, B, K, Q
	 * column = a - h
	 * row = 1 - board_dimension
	 */
	public void addPiece(char color, char piece, char column, int row){
		if (piece=='P' && (row==1 || row==board_dimension)){
			// Invalid place for a Pawn
			return;
		}
		board.setPiece(row-1,getColumnNumber(column), new Piece(color, piece)); 
	}
	
	public void movePiece(int previousColumn, int previousRow, int newColumn, int newRow){
		// If it's -1 assume the piece just goes away
		if (newColumn != -1 && newRow != -1){
			board.setPiece(newRow, newColumn, board.pieceAt(previousRow,previousColumn));
		}
		board.removePiece(previousRow, previousColumn);
	}
	
	public void changePiece(int column, int row, char newPiece){
		board.setPiece(row, column, new Piece(board.pieceAt(row,column).getColor(),newPiece));		
	}
	
	private ArrayList getValidMoves(){
		/* This returns a list of moves that are valid according to the way the pieces move, but not necessarily legal */
		ArrayList moves = new ArrayList();
		char currentPiece;
		int i, j;
		for (i=0;i<board_dimension;i++){
			for(j=0;j<board_dimension;j++){
				// If there is a piece there and it is the same color as whose turn it is
				if (board.hasPiece(i,j) && board.isColor(i,j,getTurn())){
					currentPiece = board.pieceAt(i,j).getCharacter();
					if (currentPiece=='P'){
						moves.addAll(getPawnMoves(i,j));
					}
					else if (currentPiece=='R'){
						moves.addAll(getHorizontalMoves(i,j,currentPiece));
					}
					else if (currentPiece=='B'){
						moves.addAll(getDiagonalMoves(i,j,currentPiece));
					}
					else if (currentPiece=='K'){
						moves.addAll(getKingMoves(i,j));
					}
					else if (currentPiece=='N'){
						moves.addAll(getKnightMoves(i,j));
					}
					else if (currentPiece=='Q'){
						moves.addAll(getHorizontalMoves(i,j,currentPiece));
						moves.addAll(getDiagonalMoves(i,j,currentPiece));
					}
				}
			}
		}
		return moves;
	}
	
	private ArrayList getPawnMoves(int i, int j){
		ArrayList moves = new ArrayList();
		int oneRowUp, twoRowsUp, eCol, eRow;	
		
		if (getTurn()=='W'){
			oneRowUp = i+1;
			if (board_dimension >= 6 && i==1){
				twoRowsUp = i+2;
			}
			else{
				twoRowsUp = -1;
			}
		}
		else{
			oneRowUp = i-1;
			if (board_dimension >= 6 && i==board_dimension-2){
				twoRowsUp = i-2;
			}
			else{
				twoRowsUp = -1;
			}
		}
		if (!board.hasPiece(oneRowUp,j)){ // If there is no piece in front of the pawn, it can advance one row
			if ((oneRowUp==0 || oneRowUp==board_dimension-1)){ // Possibilities for cashing in a pawn
				moves.add(new Move(getTurn(),'P',j,i,j,oneRowUp,this,'Q',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j,oneRowUp,this,'R',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j,oneRowUp,this,'B',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j,oneRowUp,this,'N',false,cNull));
			}
			else{
				moves.add(new Move(getTurn(),'P',j,i,j,oneRowUp,this));
			}
		}
		if (twoRowsUp != -1 && !board.hasPiece(oneRowUp,j) && !board.hasPiece(twoRowsUp,j)){ //If the pawn is on the second row and no pieces on 3 or 4 row, it can advance two
			moves.add(new Move(getTurn(),'P',j,i,j,twoRowsUp,this));
		}
		if (j != 0 && board.hasPiece(oneRowUp,j-1) && !isMyPiece(oneRowUp,j-1)){ // If there is a piece kiddy corner to the pawn, that piece can be taken by the pawn
			if ((oneRowUp==0 || oneRowUp==board_dimension-1)){ // Possibilities for cashing in a pawn
				moves.add(new Move(getTurn(),'P',j,i,j-1,oneRowUp,this,'Q',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j-1,oneRowUp,this,'R',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j-1,oneRowUp,this,'B',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j-1,oneRowUp,this,'N',false,cNull));
			}
			else{
				moves.add(new Move(getTurn(),'P',j,i,j-1,oneRowUp,this));
			}
		}
		if (j != board_dimension-1 && board.hasPiece(oneRowUp,j+1) && !isMyPiece(oneRowUp, j+1)){ // If there is a piece kiddy corner to the pawn, that piece can be taken by the pawn
			if ((oneRowUp==0 || oneRowUp==board_dimension-1)){ // Possibilities for cashing in a pawn
				moves.add(new Move(getTurn(),'P',j,i,j+1,oneRowUp,this,'Q',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j+1,oneRowUp,this,'R',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j+1,oneRowUp,this,'B',false,cNull));
				moves.add(new Move(getTurn(),'P',j,i,j+1,oneRowUp,this,'N',false,cNull));
			}
			else {
				moves.add(new Move(getTurn(),'P',j,i,j+1,oneRowUp,this));
			}
		}
		if (this.empazantablePawnColumn != -1){
			eCol = this.empazantablePawnColumn;
			eRow = this.empazantablePawnRow;
			
			if (!isMyPiece(eRow, eCol) && eRow==i && Math.abs(eCol-j)==1){ //If the pawn is on the same row and sitting next to the pawn that just moved two squares
				moves.add(new Move(getTurn(),'P',j,i,eCol,oneRowUp,this,cNull,true,cNull));
			}
		}
		
		return moves;
	}
	
	private ArrayList getHorizontalMoves(int i, int j, char piece){
		ArrayList moves = new ArrayList();
		int iter=1;
		
		while(i-iter>-1 && !this.board.hasPiece(i-iter,j)){
			moves.add(new Move(getTurn(),piece,j,i,j,i-iter,this));
			iter++;
		}
		if(i-iter>-1 && !isMyPiece(i-iter,j)){
			moves.add(new Move(getTurn(),piece,j,i,j,i-iter,this));
		}
		iter = 1;
		while(j+iter<board_dimension && !this.board.hasPiece(i,j+iter)){
			moves.add(new Move(getTurn(),piece,j,i,j+iter,i,this));
			iter++;
		}
		if(j+iter<board_dimension && !isMyPiece(i,j+iter)){
			moves.add(new Move(getTurn(),piece,j,i,j+iter,i,this));
		}
		iter = 1;
		while(j-iter>-1 && !this.board.hasPiece(i,j-iter)){
			moves.add(new Move(getTurn(),piece,j,i,j-iter,i,this));
			iter++;
		}
		if(j-iter>-1 && !isMyPiece(i,j-iter)){
			moves.add(new Move(getTurn(),piece,j,i,j-iter,i,this));
		}
		iter = 1;
		while(i+iter<board_dimension && !this.board.hasPiece(i+iter,j)){
			moves.add(new Move(getTurn(),piece,j,i,j,i+iter,this));
			iter++;
		}
		if(i+iter<board_dimension && !isMyPiece(i+iter,j)){
			moves.add(new Move(getTurn(),piece,j,i,j,i+iter,this));
		}
		return moves;
	}
	
	private ArrayList getDiagonalMoves(int i, int j, char piece){
		ArrayList moves = new ArrayList();
		int iter=1;
		
		while(i-iter>-1 && j-iter>-1 && !this.board.hasPiece(i-iter,j-iter)){
			moves.add(new Move(getTurn(),piece,j,i,j-iter,i-iter,this));
			iter++;
		}
		if(i-iter>-1 && j-iter>-1 && !isMyPiece(i-iter,j-iter)){
			moves.add(new Move(getTurn(),piece,j,i,j-iter,i-iter,this));
		}
		iter = 1;
		while(i-iter>-1 && j+iter<board_dimension && !this.board.hasPiece(i-iter,j+iter)){
			moves.add(new Move(getTurn(),piece,j,i,j+iter,i-iter,this));
			iter++;
		}
		if(i-iter>-1 && j+iter<board_dimension && !isMyPiece(i-iter,j+iter)){
			moves.add(new Move(getTurn(),piece,j,i,j+iter,i-iter,this));
		}
		iter = 1;
		while(i+iter<board_dimension && j-iter>-1 && !this.board.hasPiece(i+iter,j-iter)){
			moves.add(new Move(getTurn(),piece,j,i,j-iter,i+iter,this));
			iter++;
		}
		if(i+iter<board_dimension && j-iter>-1 && !isMyPiece(i+iter,j-iter)){
			moves.add(new Move(getTurn(),piece,j,i,j-iter,i+iter,this));
		}
		iter = 1;
		while(i+iter<board_dimension && j+iter<board_dimension && !this.board.hasPiece(i+iter,j+iter)){
			moves.add(new Move(getTurn(),piece,j,i,j+iter,i+iter,this));
			iter++;
		}
		if(i+iter<board_dimension && j+iter<board_dimension && !isMyPiece(i+iter,j+iter)){
			moves.add(new Move(getTurn(),piece,j,i,j+iter,i+iter,this));
		}
		
		return moves;
	}
	
	private boolean isMyPiece(int i, int j){
		return  board.isColor(i,j,getTurn());
	}
	
	private ArrayList getKingMoves(int i, int j){
		
		ArrayList moves = new ArrayList();
		
		if (i-1 > -1){
			if (j-1 > -1 && (!board.hasPiece(i-1,j-1) || !isMyPiece(i-1,j-1))){
				moves.add(new Move(getTurn(),'K',j,i,j-1,i-1,this));
			}
			if (!board.hasPiece(i-1,j) || !isMyPiece(i-1,j)){
				moves.add(new Move(getTurn(),'K',j,i,j,i-1,this));
			}
			if (j+1 < board_dimension && (!board.hasPiece(i-1,j+1) || !isMyPiece(i-1,j+1))){
				moves.add(new Move(getTurn(),'K',j,i,j+1,i-1,this));
			}
		}
		if (j-1 > -1 && (!board.hasPiece(i,j-1) || !isMyPiece(i,j-1))){
			moves.add(new Move(getTurn(),'K',j,i,j-1,i,this));
		}
		if (j+1 < board_dimension && (!board.hasPiece(i,j+1) || !isMyPiece(i,j+1))){
			moves.add(new Move(getTurn(),'K',j,i,j+1,i,this));
		}
		if (i+1 < board_dimension){
			if (j-1 > -1 && (!board.hasPiece(i+1,j-1) || !isMyPiece(i+1,j-1))){
				moves.add(new Move(getTurn(),'K',j,i,j-1,i+1,this));
			}
			if (!board.hasPiece(i+1,j) || !isMyPiece(i+1,j)){
				moves.add(new Move(getTurn(),'K',j,i,j,i+1,this));
			}
			if (j+1 < board_dimension && (!board.hasPiece(i+1,j+1) || !isMyPiece(i+1,j+1))){
				moves.add(new Move(getTurn(),'K',j,i,j+1,i+1,this));
			}
		}
		
		if (i==0 && getTurn()=='W'){
			if (this.whiteKingSideCastleAvailable && !board.hasPiece(i,j+1) && !board.hasPiece(i,j+2)){
				moves.add(new Move(getTurn(),'K',j,i,j+2,i,this,cNull,false,'K'));
			}
			if (this.whiteQueenSideCastleAvailable && !board.hasPiece(i,j-1) && !board.hasPiece(i,j-2)){
				moves.add(new Move(getTurn(),'K',j,i,j-2,i,this,cNull,false,'Q'));
			}
		}
		else if (i==board_dimension-1 && getTurn()=='B'){
			if (this.blackKingSideCastleAvailable && !board.hasPiece(i,j+1) && !board.hasPiece(i,j+2)){
				moves.add(new Move(getTurn(),'K',j,i,j+2,i,this,cNull,false,'K'));
			}
			if (this.blackQueenSideCastleAvailable && !board.hasPiece(i,j-1) && !board.hasPiece(i,j-2)){
				moves.add(new Move(getTurn(),'K',j,i,j-2,i,this,cNull,false,'Q'));
			}
		}
		return moves;
	}
	
	private ArrayList getKnightMoves(int i, int j){
		ArrayList moves = new ArrayList();
		
		if (i-1 > -1){
			if (j-2 > -1 && (!board.hasPiece(i-1,j-2) || !isMyPiece(i-1,j-2))){
				moves.add(new Move(getTurn(),'N',j,i,j-2,i-1,this));
			}
			if (j+2 < board_dimension && (!board.hasPiece(i-1,j+2) || !isMyPiece(i-1,j+2))){
				moves.add(new Move(getTurn(),'N',j,i,j+2,i-1,this));
			}
		}
		if (i-2 > -1){
			if (j-1 > -1 && (!board.hasPiece(i-2,j-1) || !isMyPiece(i-2,j-1))){
				moves.add(new Move(getTurn(),'N',j,i,j-1,i-2,this));
			}
			if (j+1 < board_dimension && (!board.hasPiece(i-2,j+1) || !isMyPiece(i-2,j+1))){
				moves.add(new Move(getTurn(),'N',j,i,j+1,i-2,this));
			}
		}
		
		if (i+1 < board_dimension){
			if (j-2 > -1 && (!board.hasPiece(i+1,j-2) || !isMyPiece(i+1,j-2))){
				moves.add(new Move(getTurn(),'N',j,i,j-2,i+1,this));
			}
			if (j+2 < board_dimension && (!board.hasPiece(i+1,j+2) || !isMyPiece(i+1,j+2))){
				moves.add(new Move(getTurn(),'N',j,i,j+2,i+1,this));
			}
		}
		if (i+2 < board_dimension){
			if (j-1 > -1 && (!board.hasPiece(i+2,j-1) || !isMyPiece(i+2,j-1))){
				moves.add(new Move(getTurn(),'N',j,i,j-1,i+2,this));
			}
			if (j+1 < board_dimension && (!board.hasPiece(i+2,j+1) || !isMyPiece(i+2,j+1))){
				moves.add(new Move(getTurn(),'N',j,i,j+1,i+2,this));
			}
		}
		
		return moves;
	}
		
	public ArrayList getLegalMoves(){
		ArrayList moves = getValidMoves(); 
		Move kingSideCastle=null;
		Move queenSideCastle=null;
		Move currentMove;
		boolean kingSideCastleValid = false;
		boolean queenSideCastleValid = false;
		
		ArrayList legalMoves = new ArrayList();
		for (int i=0;i<moves.size();i++){
			currentMove = (Move) moves.get(i);
			if (!currentMove.getState().checkForCheck(getTurn())){
				if (currentMove.getCastleType()==cNull){
					legalMoves.add(currentMove);
				}
				else if (currentMove.getCastleType()=='K'){
					kingSideCastle = currentMove;
				}
				else if (currentMove.getCastleType()=='Q'){
					queenSideCastle = currentMove;
				}
				if (currentMove.isQueenSideCastleBlankSquare()){
					queenSideCastleValid = true;
				}
				if (currentMove.isKingSideCastleBlankSquare()){
					kingSideCastleValid = true;
				}
			}
		}
		
		if (queenSideCastleValid && queenSideCastle!=null && !checkForCheck(getTurn())){
			legalMoves.add(queenSideCastle);
		}
		if (kingSideCastleValid && kingSideCastle!=null && !checkForCheck(getTurn())){
			legalMoves.add(kingSideCastle);
		}
		     
		return legalMoves;
	}
	
	public State clone(){
		return new State(turn, whiteQueenSideCastleAvailable, blackQueenSideCastleAvailable, whiteKingSideCastleAvailable, blackKingSideCastleAvailable, board);
	}
	
	public void newGame(){
		
		addPiece('W','R','a',1);
		addPiece('W','N','b',1);
		addPiece('W','B','c',1);
		addPiece('W','Q','d',1);
		addPiece('W','K','e',1);
		addPiece('W','P','a',2);
		addPiece('W','P','b',2);
		addPiece('W','P','c',2);
		addPiece('W','P','d',2);
		addPiece('W','P','e',2);
		addPiece('B','R','a',5);
		addPiece('B','N','b',5);
		addPiece('B','B','c',5);
		addPiece('B','Q','d',5);
		addPiece('B','K','e',5);
		addPiece('B','P','a',4);
		addPiece('B','P','b',4);
		addPiece('B','P','c',4);
		addPiece('B','P','d',4);
		addPiece('B','P','e',4);
		
		setTurn('W');
	}
	
	public byte[] serializeState(){
		int i,j;
		int numPieces=0;
		for (i=0;i<board_dimension;i++){
			for (j=0;j<board_dimension;j++){
				if (this.board.hasPiece(i,j)){
					numPieces++;
				}
			}
		}
		
		BitSet state = new BitSet(numPieces*4+69);
		
		int cursor = 0;
		
		if (getTurn()=='B'){
			state.set(cursor);
		}
		cursor++;
		if (whiteQueenSideCastleAvailable){
			state.set(cursor);
		}
		cursor++;
		if (whiteKingSideCastleAvailable){
			state.set(cursor);
		}
		cursor++;
		if (blackQueenSideCastleAvailable){
			state.set(cursor);
		}
		cursor++;
		if (blackKingSideCastleAvailable){
			state.set(cursor);
		}
		cursor++;
		
		for (i=0;i<board_dimension;i++){
			for (j=0;j<board_dimension;j++){
				if (this.board.hasPiece(i,j)){
					state.set(cursor);
				}
				cursor++;
			}
		}
		Piece currentPiece;
		for (i=0;i<board_dimension;i++){
			for (j=0;j<board_dimension;j++){
				if (this.board.hasPiece(i,j)){
					currentPiece = this.board.pieceAt(i,j);
					if (currentPiece.getColor()=='B'){
						state.set(cursor); //1 for black, 0 for white
					}
					cursor++;
					if (currentPiece.getCharacter()=='K'){
						state.set(cursor+2); //001
					}
					else if (currentPiece.getCharacter()=='Q'){
						state.set(cursor+1); //010
					}
					else if (currentPiece.getCharacter()=='R'){
						state.set(cursor+1); //011
						state.set(cursor+2); //011
					}
					else if (currentPiece.getCharacter()=='N'){
						state.set(cursor); //100
					}
					else if (currentPiece.getCharacter()=='B'){
						state.set(cursor); //101
						state.set(cursor+2); //101
					}
					else if (currentPiece.getCharacter()=='P' && i==empazantablePawnRow && j==empazantablePawnColumn){
						state.set(cursor); //110
						state.set(cursor+1); //110
					}
					else if (currentPiece.getCharacter()=='P'){
						state.set(cursor); //111
						state.set(cursor+1); //111
						state.set(cursor+2); //111
					}

					cursor+=3;
				}
			}
		}
		
		return toByteArray(state);
	}
	
	public Board getBoard(){
		return this.board;
	}
	
	private boolean checkForCheck(char color){
		
		State nextMove = this.clone();
		
		int kingsColumn = -1;
		int kingsRow = -1;
		int i,j;
		
		for(i=0;i<board_dimension;i++){
			for(j=0;j<board_dimension;j++){
				if (this.board.hasPiece(i,j) && this.board.isColor(i,j,color) && this.board.isCharacter(i,j,'K')){
					kingsColumn = j;
					kingsRow = i;
					break;
				}
			}
			if (kingsColumn!=-1){
				break;
			}
		}
		
		if (color=='W'){
			nextMove.setTurn('B');
		}
		else{
			nextMove.setTurn('W');
		}
		ArrayList otherColorsMoves = nextMove.getValidMoves(); // The move to take my king can still endanger his king
		
		for(i=0; i<otherColorsMoves.size();i++){
			Move possibleMove = (Move) otherColorsMoves.get(i);
			if (possibleMove.getColumn()==kingsColumn && possibleMove.getRow()==kingsRow){
				return true;
			}
		}
		
		return false;
	}
	
	public boolean isCheck(){
		return checkForCheck(getTurn());
	}
	
	
	public boolean isCheckmate(){
		return checkForCheck(getTurn()) && getLegalMoves().size()==0;
	}
	
	public boolean isStalemate(){
		return !checkForCheck(getTurn()) && getLegalMoves().size()==0;
	}
	
	public static byte[] toByteArray(BitSet bitSet) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream(bitSet.size());
		try {
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(bitSet);
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		return baos.toByteArray();
	}
	
	public static BitSet toBitSet(byte[] byteArr) {
		BitSet bitSet = null; // the new BitSet
		ByteArrayInputStream bais = new ByteArrayInputStream(byteArr);
		try {
			ObjectInputStream ois = new ObjectInputStream(bais);
			bitSet = (BitSet)ois.readObject();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}

		return bitSet;
	}

}
